﻿/*
 * File: TileSetWindow.cs
 * Developer : Brent Larsen (brentoboy@gmail.com)
 * Date: 2011-AUG-13
 * Copyright (c) 2011 Brent Larsen.
 * Distributed under the terms of the GPL v3
 *  
 * This file is part of GenX-RPG
 * http://code.google.com/p/genx-rpg/ 
 * 
 * GenX-RPG is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GenX-RPG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GenX-RPG.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace Rpg.Editor
{
    public partial class TileSetWindow : Form
    {
        private TileSetDatabase _db;
        private TileSet _tileSet;
        private Bitmap _tileBitmap;
        private bool _saved = false;

        public TileSetWindow()
        {
            InitializeComponent();

            var walkOptions = new Dictionary<int, string>()
            {
                { Tile.BLOCK_ALL, "All (No Walking)" },
                { Tile.BLOCK_NONE, "None (Walk Freely)" },
                { Tile.BLOCK_NORTH, "N" },
                { Tile.BLOCK_EAST, "E" },
                { Tile.BLOCK_SOUTH, "S" },
                { Tile.BLOCK_WEST, "W" },
                { Tile.BLOCK_NORTH | Tile.BLOCK_EAST, "NE" },
                { Tile.BLOCK_NORTH | Tile.BLOCK_SOUTH, "NS" },
                { Tile.BLOCK_NORTH | Tile.BLOCK_WEST, "NW" },
                { Tile.BLOCK_EAST | Tile.BLOCK_SOUTH, "ES" },
                { Tile.BLOCK_EAST | Tile.BLOCK_WEST, "EW" },
                { Tile.BLOCK_SOUTH | Tile.BLOCK_WEST, "SW" },
                { Tile.BLOCK_NORTH | Tile.BLOCK_EAST | Tile.BLOCK_SOUTH, "NES" },
                { Tile.BLOCK_NORTH | Tile.BLOCK_EAST | Tile.BLOCK_WEST, "NEW" },
                { Tile.BLOCK_NORTH | Tile.BLOCK_SOUTH | Tile.BLOCK_WEST, "NSW" },
                { Tile.BLOCK_EAST | Tile.BLOCK_SOUTH | Tile.BLOCK_WEST, "ESW" },
            };

            this.list_CellBlock.DisplayMember = "Value";
            this.list_CellBlock.ValueMember = "Key";
            this.list_CellBlock.DataSource = walkOptions.ToKvpList();
        }

        public TileSetWindow(TileSetDatabase db)
            : this()
        {
            Contract.Requires(db != null);
            _db = db;
            _tileSet = _db.LoadTileSet();
            _tileBitmap = (Bitmap)Image.FromStream(new MemoryStream(_tileSet.BitmapData));
            Contract.Assumes(_tileBitmap.Height % Tile.SQUARE_SIZE == 0);
            Contract.Assumes(_tileBitmap.Width % Tile.SQUARE_SIZE == 0);
            _tileSet.Width = _tileBitmap.Width / Tile.SQUARE_SIZE;
            _tileSet.Height = _tileBitmap.Height / Tile.SQUARE_SIZE;

            this.TileCanvas.Width = _tileBitmap.Width;
            this.TileCanvas.Height = _tileBitmap.Height;
            this.Width = (this.Width - this.ClientSize.Width) + this.TileCanvas.Right + this.groupBox1.Left;
            this.Height = (this.Height - this.ClientSize.Height) + Math.Max(this.groupBox3.Bottom, this.TileCanvas.Bottom) + this.groupBox1.Left;

            this.Text = "Tile Set - " + _tileSet.Name;
            this.txtName.Text = _tileSet.Name;
            this.txtCopyrightOwner.Text = _tileSet.CopyrightOwner;
            this.txtCopyrightDate.Text = _tileSet.DateOriginallyPublished;
            this.txtCopyrightNotice.Text = _tileSet.CopyrightNotice;
            this.txtLicense.Text = _tileSet.License;

            _selectTile(0, 0);
        }

        private void _selectTile(int x, int y)
        {
            var oldTile = lblXY.Tag as Tile;
            if (oldTile != null)
            {
                oldTile.Name = this.txtCellName.Text;
                oldTile.Walk = this.list_CellBlock.SelectedValue.AsInt() ?? Tile.BLOCK_ALL;
                oldTile.GroupName = this.txtCellGroup.Text;
                oldTile.GroupX = this.txtCellGroupX.Text.AsInt() ?? -1;
                oldTile.GroupY = this.txtCellGroupY.Text.AsInt() ?? -1;
            }

            var tile = _tileSet.GetTile(x, y);
            if (tile != null)
            {
                this.lblXY.Tag = tile;
                this.lblXY.Text = "{0}, {1}".f(x, y);
                this.txtCellName.Text = tile.Name;
                this.list_CellBlock.SelectedValue = tile.Walk;
                this.txtCellGroup.Text = tile.GroupName;
                this.txtCellGroupX.Text = tile.GroupX.ToString();
                this.txtCellGroupY.Text = tile.GroupY.ToString();
            }
            TileCanvas.Refresh();
        }

        private void TileCanvas_Paint(object sender, PaintEventArgs e)
        {                        
            e.Graphics.DrawImage(_tileBitmap, new Rectangle(0, 0, TileCanvas.Width, TileCanvas.Height), new Rectangle(0,0,TileCanvas.Width, TileCanvas.Height), GraphicsUnit.Pixel);

            if (_tileSet.Width.HasValue)
            {
                for (int x = 0; x < _tileSet.Width; x++)
                {
                    for (int y = 0; y < _tileSet.Height; y++)
                    {
                        Pen pen = null;
                        if (_tileSet.HasTile(x, y))
                        {
                            if (_tileSet.GetTile(x, y) == lblXY.Tag)
                                pen = Pens.Yellow;
                            else
                                pen = Pens.DarkGreen;
                        }
                        else
                        {
                            pen = Pens.Red;
                        }
                        e.Graphics.DrawRectangle(pen, x * Tile.SQUARE_SIZE, y * Tile.SQUARE_SIZE, Tile.SQUARE_SIZE - 1, Tile.SQUARE_SIZE - 1);
                    }
                }
            }
        }

        private void TileCanvas_MouseUp(object sender, MouseEventArgs e)
        {
            int x = e.X / Tile.SQUARE_SIZE;
            int y = e.Y / Tile.SQUARE_SIZE;

            _selectTile(x, y);
        }

        private void menuFile_ImportBitmap_Click(object sender, EventArgs e)
        {
            // not implemented
        }

        private void menuFile_Save_Click(object sender, EventArgs e)
        {
            try
            {
                _save();
                this.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void _save()
        {
            // copy values out of text boxes
            _selectTile(-1, -1);
            _tileSet.Name = this.txtName.Text;
            _tileSet.CopyrightOwner = this.txtCopyrightOwner.Text;
            _tileSet.DateOriginallyPublished = this.txtCopyrightDate.Text;
            _tileSet.CopyrightNotice = this.txtCopyrightNotice.Text;
            _tileSet.License = this.txtLicense.Text;

            // save to db
            _db.SaveTileSet(_tileSet);

            // update the main menu
            var menuTileSets = (this.Owner as MenuWindow).menuTileSets;
            var menuItem = menuTileSets.DropDownItems.OfType<ToolStripMenuItem>().Single(x => x.Tag as string == _db.DbFileName);
            menuItem.Text = _tileSet.Name;

            // dont ask to save when the form closes
            _saved = true;
        }

        private void menuFile_Close_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void MapEditWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!_saved)
            {
                var response = MessageBox.Show("Save?", "Wait!", MessageBoxButtons.YesNoCancel);
                switch (response)
                {
                    case System.Windows.Forms.DialogResult.Yes:
                        try
                        {
                            _save();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                            e.Cancel = true;
                        }
                        break;

                    case System.Windows.Forms.DialogResult.No:
                        e.Cancel = false;
                        break;

                    case System.Windows.Forms.DialogResult.Cancel:
                        e.Cancel = true;
                        break;

                    default:
                        Contract.UnexpectedCase(response.ToString());
                        break;
                }
            }
        }

        private void menuFile_Export_Click(object sender, EventArgs e)
        {
            using (var dialog = new SaveFileDialog())
            {
                dialog.AddExtension = true;
                dialog.CheckPathExists = true;
                dialog.DefaultExt = ".tiles";
                try { dialog.FileName = _db.GetTileSetName() + ".tiles"; } catch {}
                dialog.Filter = "GenX RPG Tilesets (*.tiles)|*.tiles";
                dialog.FilterIndex = 1;
                dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                dialog.OverwritePrompt = true;
                dialog.RestoreDirectory = true;
                dialog.Title = "Save As...";
                dialog.ValidateNames = true;

                if (dialog.ShowDialog() != DialogResult.Cancel)
                {
                    _db.SaveAs(new FileInfo(dialog.FileName));
                }
            }
        }
    }
}
